package com.wzl.policy.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * ftp工具类
 *
 * @author weizhongli
 * @since 2022-08-03 14:17
 */
@Slf4j
@Component
public class FtpUtil {

    /**
     * FTP基础目录
     **/
    private final String BASE_PATH = "";

    /**
     * 本地字符编码
     **/
    private static String LOCAL_CHARSET = "GBK";

    /**
     * FTP协议里面，规定文件名编码为iso-8859-1
     **/
    private static final String SERVER_CHARSET = "ISO-8859-1";

    /**
     * UTF-8字符编码
     **/
    private static final String CHARSET_UTF8 = "UTF-8";

    /**
     * OPTS UTF8字符串常量
     **/
    private static final String OPTS_UTF8 = "OPTS UTF8";

    /**
     * FTPClient对象
     **/
    private static FTPClient ftpClient = null;


    /**
     * 连接FTP服务器
     * @param ip  FTP服务器hostname
     * @param port  端口
     * @param username  账号
     * @param password 密码
     */
    public boolean login(String ip, int port, String username, String password) {
        ftpClient = new FTPClient();
        try {
            ftpClient.connect(ip, port);
            ftpClient.login(username, password);
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            int reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                closeConnect();
                log.error("FTP服务器连接失败");
            }
            return true;
        } catch (Exception e) {
            log.error("FTP登录失败", e);
        }
        return false;
    }

    /**
     * 关闭FTP连接
     */
    public void closeConnect() {
        if (ftpClient != null && ftpClient.isConnected()) {
            try {
                ftpClient.logout();
                ftpClient.disconnect();
            } catch (IOException e) {
                log.error("关闭FTP连接失败", e);
            }
        }
    }

    /**
     * FTP服务器路径编码转换
     *
     * @param ftpPath FTP服务器路径
     * @return String
     */
    private static String changeEncoding(String ftpPath) {
        String directory = null;
        try {
            if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(OPTS_UTF8, "ON"))) {
                LOCAL_CHARSET = CHARSET_UTF8;
            }
            directory = new String(ftpPath.getBytes(LOCAL_CHARSET), SERVER_CHARSET);
        } catch (Exception e) {
            log.error("路径编码转换失败", e);
        }
        return directory;
    }


    /**
     * 获取指定ftp目录下的文件
//     * @param ip  FTP服务器hostname
//     * @param port  端口
//     * @param username  账号
//     * @param password  密码
     * @param remotePath  FTP服务器上文件所在相对路径，例如：test/123
     * @return   返回文件的集合对象
     */
    public List<FTPFile> getFileList(String remotePath) {
        // 登录
        // login(ip, port, username, password);
        ArrayList<FTPFile> fileList = new ArrayList();
        FTPFile[] ftpFiles = null;
        try {

            String path = changeEncoding(BASE_PATH + remotePath);
            // 判断是否存在该目录
            if (!ftpClient.changeWorkingDirectory(path)) {
                log.error(BASE_PATH + remotePath + "该目录不存在");
                return fileList;
            }
            ftpClient.enterLocalPassiveMode(); // 设置被动模式
            String[] fs = ftpClient.listNames();
            // 判断该目录下是否有文件
            if (fs == null || fs.length == 0) {
                //log.error(BASE_PATH + remotePath + "该目录下没有文件");
                return fileList;
            }

            //得到当前ftp目录下的文件列表
             ftpFiles = ftpClient.listFiles();
            for (int i = 0; i < ftpFiles.length; i++)
            {
                FTPFile file = ftpFiles[i];
                fileList.add(file);
            }

        }catch (IOException e) {
            e.printStackTrace();
            log.error("获取文件失败", e);
        }
//        finally {
//            closeConnect();
//        }
        return fileList;
    }


    /**
     *  ftp移动文件到指定目录
//     * @param ip  FTP服务器hostname
//     * @param port  端口
//     * @param username  账号
//     * @param password  密码
     * @param fromdir 从这个文件路径
     * @param fileName 文件名称
     * @param todir 目标路径
     * @return 是否成功
     */
    public boolean moveFtpFileToDir(String folder,String fromdir,String fileName, String todir) {
        try {
            //如果目录不存在则创建目录
            if (!ftpClient.changeWorkingDirectory("/" + todir + "/" + folder)) {
                boolean b = ftpClient.makeDirectory("/" + todir + "/" + folder);
            }
            return ftpClient.rename("/" + fromdir + "/" + folder + "/" + fileName, "/" + todir + "/" + folder + "/" + fileName);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("文件移动失败", e);
        }
        return false;
    }


    /**
     * 读取文件内容为List 每行作为一个List的节点
     * @param FileName  读取的文件名字
     * @param remotePath 文件所在路径
     * @return
     */
    public List readFtpFile(String FileName, String remotePath) {
        List list = new ArrayList();
        try {
            boolean b = ftpClient.changeWorkingDirectory(remotePath);
            InputStream in = ftpClient.retrieveFileStream(FileName);
            list = readFileIntoList(in);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("文件读取失败", e);
        }
        return list;
    }

    /**
     * 从输入流中读取文件到List 每行作为一个List的节点
     *
     * @param inStream
     * @return
     * @throws IOException
     */
    public static List readFileIntoList(InputStream inStream) throws IOException {
        String line = null;
        List result = null;
        if (inStream != null) {
            result = new ArrayList();
            BufferedReader in = new BufferedReader(new InputStreamReader(inStream));
            while ((line = in.readLine()) != null) {
                line = line.trim();
                if (line.length() > 0) {
                    result.add(line.trim());
                }
            }
            if (result.size() <= 0) {
            }
            in.close();
            inStream.close();
            ftpClient.completePendingCommand();
        }
        return result;
    }

    /**
     * 获取指定文件夹下面的文件夹
     * 列出FTP服务器上面当前目录的所有的目录
     */
    public List<String> getFolderList(String remotePath) {

        ArrayList fileFolderList = new ArrayList();
        try {
            String path = changeEncoding(BASE_PATH + remotePath);
            // 判断是否存在该目录
            if (!ftpClient.changeWorkingDirectory(path)) {
                log.error(BASE_PATH + remotePath + "该目录不存在");
                return fileFolderList;
            }

            ftpClient.enterLocalPassiveMode(); // 设置被动模式
            String[] fs = ftpClient.listNames();
            // 判断该目录下是否有文件
            if (fs == null || fs.length == 0) {
                log.error(BASE_PATH + remotePath + "该目录下没有文件");
                return fileFolderList;
            }

            //得到当前ftp目录下的文件列表
            FTPFile[] ftpFiles = ftpClient.listFiles();
            for (int i = 0; i < ftpFiles.length; i++) {
                FTPFile file = ftpFiles[i];
                if(file.isDirectory()){
                    fileFolderList.add(file.getName());
                }
            }
        }catch (IOException e) {
            e.printStackTrace();
            log.error("获取文件夹列表失败", e);
        }
        return fileFolderList;
    }

    public boolean deleteFolder(String folder) {
        try {
            return ftpClient.removeDirectory(folder);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("文件移动失败", e);
        }
        return false;
    }
}